package com.example;

import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.constant.SockAddrFamily;

import java.lang.foreign.Arena;
import java.lang.foreign.Linker;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.lang.foreign.SymbolLookup;
import java.net.InetAddress;
import java.nio.file.Path;
import java.util.List;

public class Utils {

    /**
     * 获取路由器的MAC地址，构造以太帧时需要。
     *
     * @return 网关的MAC地址，6字节
     */
    public static byte[] getGatewayMac() throws Throwable {

        try (Arena arena = Arena.ofConfined()) {

            // Obtain an instance of the native linker
            Linker linker = Linker.nativeLinker();

            // Locate the address of the C function signature
            SymbolLookup lu = SymbolLookup.libraryLookup(Path.of("lib\\ip_lookup.dll"), arena);
            MemorySegment ip_lookup_addr = lu.find("get_gateway_mac_addr").get();

            // Create a description of the C function
            FunctionDescriptor lookup_sig =
                    FunctionDescriptor.of(ValueLayout.JAVA_LONG);

            // Create a downcall handle for the C function    
            MethodHandle get_gateway_mac_addr = linker.downcallHandle(ip_lookup_addr, lookup_sig);

            // Call the C function directly from Java
            // return (long)get_gateway_mac_addr.invokeExact();

            long macLong = (long) get_gateway_mac_addr.invokeExact();
            byte[] macBytes = new byte[6];
            for (int i = 0; i < 6; i++) {
                macBytes[i] = (byte) (macLong >>> (40 - (i * 8)));
            }
            return macBytes;
        }
    }

    public static PcapIf getPcapIf() throws Exception {
        InetAddress addr = InetAddress.getLocalHost();
//        System.out.printf("Local IP address: %s%n", addr.getHostAddress());
        List<PcapIf> allDevices = Pcap.findAllDevs();

        for (PcapIf pcapIf : allDevices) {
            List<PcapIf.PcapAddr<?>> addresses = pcapIf.addresses();
            for (PcapIf.PcapAddr<?> address : addresses) {
                String ip = address.socketAddress().toString();
                if (address.socketAddress().isFamily(SockAddrFamily.INET)) {
                    if (ip != null && ip.contains(addr.getHostAddress())) {
                        // 返回指定的设备对象
                        return pcapIf;
                    }
                }

            }
        }
        return null;
    }

}
